EHF: Introduce preempted return code parameter to ehf_allow_ns_preemption()
authorJeenu Viswambharan <[email protected]>
Mon, 22 Jan 2018 12:29:12 +0000 (12:29 +0000)
committerJeenu Viswambharan <[email protected]>
Tue, 27 Feb 2018 13:46:33 +0000 (13:46 +0000)
When a Yielding SMC is preempted, it's possible that Non-secure world is
resumed afterwards. In this case, Non-secure execution would find itself
in a state where the SMC has returned. However, the dispatcher might not
get an opportunity to populate the corrected return code for having
been preempted, and therefore the caller of the Yielding SMC cannot
reliably determine whether the SMC had successfully completed or had
been preempted.

To solve this, this patch introduces a new parameter to the
ehf_allow_ns_preemption() API. An SPD, through this parameter, would
provide the expected error code when a Yielding SMC is preempted. EHF
can then populate the specified value in x0 of the Non-secure context so
that the caller of the Yielding SMC correctly identifies the SMC return
as a preemption.

Documentation updates to follow.

Change-Id: Ia9c3f8f03f9d72d81aa235eaae2ee0374b972e1e
Signed-off-by: Jeenu Viswambharan <[email protected]>
bl31/ehf.c
include/bl31/ehf.h

index 39ee6355efb327803ec56b0a3ca4327bf4106e89..8673564f25fe7749d823a9518cd20d92167b6f81 100644 (file)
@@ -9,6 +9,8 @@
  */
 
 #include <assert.h>
+#include <context.h>
+#include <context_mgmt.h>
 #include <cpu_data.h>
 #include <debug.h>
 #include <ehf.h>
@@ -308,15 +310,17 @@ static void *ehf_entering_normal_world(const void *arg)
 /*
  * Program Priority Mask to the original Non-secure priority such that
  * Non-secure interrupts may preempt Secure execution, viz. during Yielding SMC
- * calls.
+ * calls. The 'preempt_ret_code' parameter indicates the Yielding SMC's return
+ * value in case the call was preempted.
  *
  * This API is expected to be invoked before delegating a yielding SMC to Secure
  * EL1. I.e. within the window of secure execution after Non-secure context is
  * saved (after entry into EL3) and Secure context is restored (before entering
  * Secure EL1).
  */
-void ehf_allow_ns_preemption(void)
+void ehf_allow_ns_preemption(uint64_t preempt_ret_code)
 {
+       cpu_context_t *ns_ctx;
        unsigned int old_pmr __unused;
        pe_exc_data_t *pe_data = this_cpu_data();
 
@@ -333,6 +337,15 @@ void ehf_allow_ns_preemption(void)
                panic();
        }
 
+       /*
+        * Program preempted return code to x0 right away so that, if the
+        * Yielding SMC was indeed preempted before a dispatcher gets a chance
+        * to populate it, the caller would find the correct return value.
+        */
+       ns_ctx = cm_get_context(NON_SECURE);
+       assert(ns_ctx);
+       write_ctx_reg(get_gpregs_ctx(ns_ctx), CTX_GPREG_X0, preempt_ret_code);
+
        old_pmr = plat_ic_set_priority_mask(pe_data->ns_pri_mask);
 
        EHF_LOG("Priority Mask: 0x%x => 0x%x\n", old_pmr, pe_data->ns_pri_mask);
index be8c957cc9b3ee46aa5d8a85f655bba997f176f7..f963f8d0cf35cf2ad383f670971e7630e1af1207 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -82,7 +82,7 @@ void ehf_init(void);
 void ehf_activate_priority(unsigned int priority);
 void ehf_deactivate_priority(unsigned int priority);
 void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler);
-void ehf_allow_ns_preemption(void);
+void ehf_allow_ns_preemption(uint64_t preempt_ret_code);
 unsigned int ehf_is_ns_preemption_allowed(void);
 
 #endif /* __ASSEMBLY__ */